﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CCTV.Common;
using System.IO.Ports;
using System.Diagnostics;
using CCTV.Protocols;

namespace CCTV.SerialPorts
{
    public sealed class PelcoDPortManager : ICameraSerialPort
    {
        static readonly PelcoDPortManager _instance = new PelcoDPortManager();

        public static PelcoDPortManager Instance
        {
            get
            {
                return _instance;
            }
        }

        private PelcoDPortManager()
        {
        }

        static PelcoD dProtocol = new PelcoD();

      

        public List<string> GetAvailableCommands()
        {
            List<string> cmds = new List<string>();
            foreach (AppConstants.PelcoDCommandsEnum cmd in Enum.GetValues(typeof(AppConstants.PelcoDCommandsEnum)))
            {
                cmds.Add(cmd.ToString());
            }
            return cmds;
        }

        public AppConstants.CommandType GetCommandType()
        {
            return AppConstants.CommandType.PelcoD;
        }

        public void SendCommand(string issuedCommand, uint cameraId, uint cameraSpeed, SerialPortBase serialPortToUse)
        {
            AppConstants.PelcoDCommandsEnum command = (AppConstants.PelcoDCommandsEnum)Enum.Parse(typeof(AppConstants.PelcoDCommandsEnum), issuedCommand);
            byte[] cmd = null;
            //dProtocol.CameraTilt(cameraId, D.Tilt.Up, cameraSpeed);

            switch (command)
            {
                case AppConstants.PelcoDCommandsEnum.MoveUp:
                    cmd = dProtocol.CameraTilt(cameraId, PelcoD.Tilt.Up, cameraSpeed);
                    break;
                case AppConstants.PelcoDCommandsEnum.MoveDown:
                    cmd = dProtocol.CameraTilt(cameraId, PelcoD.Tilt.Down, cameraSpeed);
                    break;
                case AppConstants.PelcoDCommandsEnum.MoveLeft:
                    cmd = dProtocol.CameraPan(cameraId, PelcoD.Pan.Left, cameraSpeed);
                    break;
                case AppConstants.PelcoDCommandsEnum.MoveRight:
                    cmd = dProtocol.CameraPan(cameraId, PelcoD.Pan.Right, cameraSpeed);
                    break;
                case AppConstants.PelcoDCommandsEnum.ZoomTele:
                    cmd = dProtocol.CameraZoom(cameraId, PelcoD.Zoom.Tele);
                    break;
                case AppConstants.PelcoDCommandsEnum.ZoomWide:
                    cmd = dProtocol.CameraZoom(cameraId, PelcoD.Zoom.Wide);
                    break;
                case AppConstants.PelcoDCommandsEnum.Stop:
                    cmd = dProtocol.CameraStop(cameraId);
                    break;
                case AppConstants.PelcoDCommandsEnum.BeginPano:
                    cmd = dProtocol.Pattern(cameraId, PelcoD.PatternAction.Run);
                    break;
                case AppConstants.PelcoDCommandsEnum.Wiper:
                    cmd = dProtocol.SetAuxiliary(cameraId, 0x01, PelcoD.AuxAction.Set);
                    break;
                case AppConstants.PelcoDCommandsEnum.FocusNear:
                    cmd = dProtocol.CameraFocus(cameraId, PelcoD.Focus.Near);
                    break;
                case AppConstants.PelcoDCommandsEnum.FocusFar:
                    cmd = dProtocol.CameraFocus(cameraId, PelcoD.Focus.Far);
                    break;
                case AppConstants.PelcoDCommandsEnum.IrisOpen:
                    cmd = dProtocol.CameraIrisSwitch(cameraId, PelcoD.Iris.Open);
                    break;
                case AppConstants.PelcoDCommandsEnum.IrisClose:
                    cmd = dProtocol.CameraIrisSwitch(cameraId, PelcoD.Iris.Close);
                    break;
                case AppConstants.PelcoDCommandsEnum.GetPreset:
                    cmd = dProtocol.Preset(cameraId, (byte)cameraSpeed, PelcoD.PresetAction.Goto);
                    break;
                case AppConstants.PelcoDCommandsEnum.SetPreset:
                    cmd = dProtocol.Preset(cameraId, (byte)cameraSpeed, PelcoD.PresetAction.Set);
                    break;

                case AppConstants.PelcoDCommandsEnum.Menu:
                    cmd = dProtocol.Preset(cameraId, 0x5F, PelcoD.PresetAction.Set);
                    break;
                case AppConstants.PelcoDCommandsEnum.Defog:
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.Menu, 1, 100, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.MoveDown, 2, 45, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.IrisOpen, 1, 45, false, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.MoveDown, 5, 45, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.IrisOpen, 1, 45, false, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.MoveDown, 1, 45, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.IrisOpen, 1, 45, false, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.MoveUp, 3, 45, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.IrisOpen, 1, 45, false, cameraId, serialPortToUse);
                    return;
                case AppConstants.PelcoDCommandsEnum.IR:
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.Menu, 1, 100, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.MoveDown, 2, 45, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.IrisOpen, 1, 45, false, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.MoveDown, 2, 45, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.IrisOpen, 1, 45, false, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.MoveUp, 3, 45, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.IrisOpen, 1, 45, false, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.MoveUp, 3, 45, cameraId, serialPortToUse);
                    DoMenuThings(AppConstants.PelcoDCommandsEnum.IrisOpen, 1, 45, false, cameraId, serialPortToUse);
                    return;
                default:
                    break;

            }
            serialPortToUse.SendValue(cmd);
        }

        #region private
        private void DoMenuThings(AppConstants.PelcoDCommandsEnum command, int numberOfTimes, int delay, uint cameraId, SerialPortBase serialPortToUse)
        {
            DoMenuThings(command, numberOfTimes, delay, true, cameraId, serialPortToUse);
        }

        private void DoMenuThings(AppConstants.PelcoDCommandsEnum command, int numberOfTimes, int delay, bool useStop, uint cameraId, SerialPortBase serialPortToUse)
        {
            for (int i = 0; i < numberOfTimes; i++)
            {
                SendCommand(command.ToString(), cameraId, 0, serialPortToUse);
                System.Threading.Thread.Sleep(delay);
                if (useStop)
                {
                    SendCommand(AppConstants.PelcoDCommandsEnum.Stop.ToString(), cameraId, 0, serialPortToUse);
                    System.Threading.Thread.Sleep(delay);
                }
            }
        }
        #endregion
    }


}